﻿#pragma once

#include <entt.hpp>
#include "SourceCode/Renderer/EditorCamera.h"

class b2World;

namespace Hazal
{
	class CEntity;
	class CSceneHierarchyPanel;
	class CSceneSerializer;

	class CScene
	{
	friend class CEntity;
	friend class CSceneHierarchyPanel;
	friend class CSceneSerializer;

	public:
		CScene();

		~CScene();

	public:
		/// <summary>
		/// Static func. Copy the resources from the source scene. 
		/// </summary>
		/// <param name="pSrcScene">Source scene</param>
		/// <returns></returns>
		static Ref<CScene> Copy(Ref<CScene> pOther);

	public:
		/// <summary>
		/// Update real run time per frame
		/// </summary>
		/// <param name="fTimeSpan"></param>
		void OnUpdateRuntime(float fTimeSpan);

		/// <summary>
		/// Update engine editor per frame
		/// </summary>
		/// <param name="fTimeSpan"></param>
		/// <param name="camera"></param>
		void OnUpdateEditor(float fTimeSpan, CEditorCamera& camera);

		/// <summary>
		/// Create an entity
		/// </summary>
		/// <param name="strTag">A tag of created entity</param>
		/// <returns></returns>
		CEntity CreateEntity(const std::string& strTag = std::string());

		/// <summary>
		/// Create an entity with uuid
		/// </summary>
		/// <param name="id"></param>
		/// <param name="strTag"></param>
		/// <returns></returns>
		CEntity CreateEntityWithUUID(uint64_t id, const std::string& strTag = std::string());

		/// <summary>
		/// Destroy an entity
		/// </summary>
		/// <param name="entity"></param>
		void DestroyEntity(CEntity& entity);

		/// <summary>
		/// Change the viewport size
		/// </summary>
		/// <param name="unWidth"></param>
		/// <param name="unHeight"></param>
		void OnViewportResize(uint32_t unWidth, uint32_t unHeight);

		/// <summary>
		/// Set window render result viewport focuse state
		/// </summary>
		/// <param name="bState"></param>
		inline void SetViewportFocused(bool bState) { m_bViewportFoucus = bState; }

		/// <summary>
		///  Get primary camera in scene
		/// </summary>
		/// <returns></returns>
		CEntity GetPrimaryCamera();

		/// <summary>
		///	The action when runtime start 
		/// </summary>
		void OnRunTimeStart();

		/// <summary>
		/// The action when runtime stop
		/// </summary>
		void OnRunTimeStop();

		/// <summary>
		/// Duplicate a new entitty from given entitty
		/// </summary>
		/// <param name="entt"></param>
		void DuplicateEntity(CEntity entt);

	private:
		template<typename T>
		void OnComponentAdded(CEntity& entity, T& component);

	private:
		entt::registry m_registry;

		bool m_bViewportFoucus = true;

		uint32_t m_unViewportWidth = 0;		///< The width of the active scene
		uint32_t m_unViewportHeight = 0;	///< The height of the active scene

		b2World* m_pPhysicsWorld = nullptr;			///< Create a box2d world
	};
}
